package cz.semjob.learning.classifier.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import weka.classifiers.Classifier;
import cz.semjob.learning.classifier.benchmark.ClassifierBenchmarkResults;
import cz.semjob.learning.data.TaxonomyLearningException;
import cz.semjob.learning.instances.creator.IInstanceCreator;

@Component
public class ClassifierIO {

	private static Logger logger = Logger.getLogger(ClassifierIO.class);

	public void exportClassifierToFile(String exportPath, Classifier classifier)
			throws TaxonomyLearningException {
		try {
			exportObject(exportPath, classifier);
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e);
			throw new TaxonomyLearningException(e);
		}

	}

	public Classifier importClassifierFromFile(String importPath)
			throws TaxonomyLearningException {
		Classifier classifier = null;
		try {
			classifier = (Classifier) importObject(importPath);
		} catch (IOException i) {
			i.printStackTrace();
			logger.error(i);
			throw new TaxonomyLearningException(i);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			logger.error(e);
			throw new TaxonomyLearningException(e);
		}
		return classifier;
	}

	public ClassifierBenchmarkResults importClassifierBenchmarkResults(
			String importPath) throws TaxonomyLearningException {
		ClassifierBenchmarkResults classifierBenchmarkResults = null;
		try {
			classifierBenchmarkResults = (ClassifierBenchmarkResults) importObject(importPath);
		} catch (IOException i) {
			i.printStackTrace();
			logger.error(i);
			throw new TaxonomyLearningException(i);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			logger.error(e);
			throw new TaxonomyLearningException(e);
		}
		return classifierBenchmarkResults;
	}

	public IInstanceCreator importTextInstanceCreator(String importPath)
			throws TaxonomyLearningException {
		IInstanceCreator textInstanceCreator = null;
		try {
			textInstanceCreator = (IInstanceCreator) importObject(importPath);
		} catch (IOException i) {
			i.printStackTrace();
			logger.error(i);
			throw new TaxonomyLearningException(i);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			logger.error(e);
			throw new TaxonomyLearningException(e);
		}
		return textInstanceCreator;
	}

	public void exportTextInstanceCreatorToFile(String exportPath,
			IInstanceCreator textInstanceCreator)
			throws TaxonomyLearningException {
		try {
			exportObject(exportPath, textInstanceCreator);
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e);
			throw new TaxonomyLearningException(e);
		}

	}

	public void exportClassifierBenchmarkResultsToFile(String exportPath,
			ClassifierBenchmarkResults classifierBenchmarkResults)
			throws TaxonomyLearningException {
		try {
			exportObject(exportPath, classifierBenchmarkResults);
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e);
			throw new TaxonomyLearningException(e);
		}

	}

	private Serializable importObject(String importPath) throws IOException,
			ClassNotFoundException {
		File importFile = new File(importPath);
		if (!importFile.getParentFile().isDirectory()) {
			throw new IOException("Could not import object, '" + importPath
					+ "' is not a directory.");
		}
		Serializable serializable = null;
		FileInputStream fileIn = new FileInputStream(importPath);
		ObjectInputStream in = new ObjectInputStream(fileIn);
		serializable = (Serializable) in.readObject();
		in.close();
		fileIn.close();

		return serializable;
	}

	private void exportObject(String exportPath, Serializable object)
			throws IOException {
		File exportFile = new File(exportPath);
		if (!exportFile.getParentFile().isDirectory()) {
			throw new IOException("Could not export object, '"
					+ exportFile.getParentFile() + "' is not a directory.");
		}
		FileOutputStream fileOut = new FileOutputStream(exportPath);
		ObjectOutputStream out;
		out = new ObjectOutputStream(fileOut);
		out.writeObject(object);
		out.close();
		fileOut.close();
	}

}
